package dstation.client;

import java.util.Comparator;
import java.util.Date;
import java.util.List;

import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.MenuItemSeparator;
import com.google.gwt.user.client.ui.NamedFrame;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;

import dstation.databeans.RobotBean;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HTML;

import dstation.databeans.ResultBean;
import dstation.databeans.ResultDisplayBean;
import dstation.databeans.SensorBean;
import dstation.databeans.SensorBean.SensorType;
import dstation.databeans.TestBean;
import dstation.testbeans.EncoderTestBean;
import dstation.testbeans.EncoderTestBean.Direction;
import dstation.testbeans.RFTestBean;

import com.google.gwt.user.client.ui.DecoratedStackPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.IntegerBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.user.cellview.client.TextColumn;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class DStation implements EntryPoint {

	private final AddRobotAsync asyncAccess = GWT.create(AddRobot.class);
	protected ListDataProvider<RobotBean> robotData;
	protected ListDataProvider<SensorBean> sensorData;
	protected ListDataProvider<ResultDisplayBean> resultData;
	protected ListDataProvider<TestBean> testData;


	/**
	 * @wbp.parser.entryPoint
	 */
	public void onModuleLoad() {


		if(RootPanel.get("recenttests")!=null){
			RootPanel.get("recenttests").add(new HTML("<h2>Recent Tests</h2>"));
			RootPanel.get("recenttests").add(this.buildResultsTable(-1, 15, null, null, null));
		}
		if(RootPanel.get("search")!=null){
			createResultSearch();
		}
		if(RootPanel.get("viewtests")!=null){
			createViewTests();
		}
		if(RootPanel.get("testeditcreate")!=null){
			createCreateTest();
		}
		if(RootPanel.get("menu")!=null){
			createMenu();
		}
		if(RootPanel.get("robotTable")!=null){
			createRobotTable();
		}
		if(RootPanel.get("robot")!=null){
			createRobotView();
		}
	}
	
	

	private void createResultSearch() {
		final RootPanel rootPanel = RootPanel.get("search");
		
		Grid grid = new Grid(5, 2);
		rootPanel.add(grid);
		
		HTML htmlsearch = new HTML("<h2>Search:</h2>", true);
		grid.setWidget(0, 0, htmlsearch);
		
		Label lblRobotName = new Label("Robot Name:");
		grid.setWidget(1, 0, lblRobotName);
		
		final TextBox robotBox = new TextBox();
		grid.setWidget(1, 1, robotBox);
		
		Label lblTestName = new Label("Test Name:");
		grid.setWidget(2, 0, lblTestName);
		
		final TextBox testBox = new TextBox();
		testBox.setText("");
		grid.setWidget(2, 1, testBox);
		
		Label lblSensorName = new Label("Sensor Name:");
		grid.setWidget(3, 0, lblSensorName);
		
		final TextBox sensorBox = new TextBox();
		grid.setWidget(3, 1, sensorBox);
		
		Button btnSearch = new Button("Search");
		grid.setWidget(4, 1, btnSearch);
		
		final HTML resultTitle = new HTML("<h2>Recent Tests</h2>");
		rootPanel.add(resultTitle); 
		rootPanel.add(buildResultsTable(-1, 15, null, null, null));
		
		btnSearch.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				resultTitle.setHTML("<h2>Search Results</h2>");
				rootPanel.remove(rootPanel.getWidgetCount()-1);
				String bot = robotBox.getText().length() > 0? robotBox.getText() : null;
				String test = testBox.getText().length() > 0? testBox.getText() : null;
				String sensor = sensorBox.getText().length() > 0? sensorBox.getText() : null;
				rootPanel.add(buildResultsTable(-1, 15, bot, test, sensor));
			}
		});
	}



	private void createViewTests(){
		RootPanel rootPanel = RootPanel.get("viewtests");

		final CellTable<TestBean> cellTable = new CellTable<TestBean>();
		rootPanel.add(cellTable);

		asyncAccess.getTestTable(new AsyncCallback<List<TestBean>>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			@Override
			public void onSuccess(List<TestBean> result) {
				testData = new ListDataProvider<TestBean>(result);

				TextColumn<TestBean> textColumn = new TextColumn<TestBean>() {
					@Override
					public String getValue(TestBean object) {
						return object.getName();
					}
				};
				cellTable.addColumn(textColumn, "Test Name");

				TextColumn<TestBean> textColumn_1 = new TextColumn<TestBean>() {
					@Override
					public String getValue(TestBean object) {
						return object.getType().toString();
					}
				};
				cellTable.addColumn(textColumn_1, "Sensor Type");

				TextColumn<TestBean> textColumn_2 = new TextColumn<TestBean>() {
					@Override
					public String getValue(TestBean object) {
						return object.getDescription().toString();
					}
				};
				cellTable.addColumn(textColumn_2, "Description");

				Column<TestBean, String> column = new Column<TestBean, String>(new ButtonCell()) {
					@Override
					public String getValue(TestBean object) {
						return "Edit " + object.getName();
					}
				};
				column.setFieldUpdater(new FieldUpdater<TestBean,String>(){
					@Override
					public void update(int index, TestBean object, String value) {
						final FormPanel form = new FormPanel(new NamedFrame("_self"));
						form.setAction("edittest.do");
						form.setMethod(FormPanel.METHOD_POST);
						form.setWidget(new Hidden("id",object.getTestid()+""));
						form.setEncoding(FormPanel.ENCODING_URLENCODED);
						form.submit();
					}
				});
				cellTable.addColumn(column);

				testData.addDataDisplay(cellTable);
			}
		});
	}

	private void createCreateTest(){
		final RootPanel rootPanel = RootPanel.get("testeditcreate");

		final int testid = rootPanel.getTitle().equals("")? -1 : Integer.parseInt(rootPanel.getTitle());
		rootPanel.setTitle("");
		final String dialogText = testid==-1? "Enter the new test name:":"Reenter the test name";
		final String buttonText = testid==-1? "Create Test":"Modify Test";

		final DecoratedStackPanel decoratedStackPanel = new DecoratedStackPanel();
		rootPanel.add(decoratedStackPanel);

		final ListBox comboBox = new ListBox();

		decoratedStackPanel.add(comboBox, "Sensor Type", false);
		comboBox.setSize("100%", "100%");

		comboBox.addItem("Encoder");
		comboBox.addItem("Rangefinder");

		final TextArea descriptionTextArea = new TextArea();
		descriptionTextArea.setVisibleLines(9);
		decoratedStackPanel.add(descriptionTextArea, "Description", false);

		final Grid encGrid = new Grid(4, 2);
		decoratedStackPanel.add(encGrid, "Test Properties", false);
		encGrid.setSize("100%", "100%");

		Label lblWheelSpeed = new Label("Wheel Speed:");
		encGrid.setWidget(0, 0, lblWheelSpeed);

		final IntegerBox speedBox = new IntegerBox();
		encGrid.setWidget(0, 1, speedBox);

		Label lblSampleRate = new Label("Sample Rate:");
		encGrid.setWidget(1, 0, lblSampleRate);

		final IntegerBox sampleRateBox = new IntegerBox();
		encGrid.setWidget(1, 1, sampleRateBox);

		Label lblDirection = new Label("Direction:");
		encGrid.setWidget(2, 0, lblDirection);

		final ListBox directionComboBox = new ListBox();
		for(Direction d: EncoderTestBean.Direction.values()){
			directionComboBox.addItem(d.toString());
		}
		encGrid.setWidget(2, 1, directionComboBox);

		final Button btnCreateTest = new Button(buttonText);
		btnCreateTest.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				final DialogPrompt d = new DialogPrompt(dialogText);
				d.show(btnCreateTest.getAbsoluteLeft()+5, btnCreateTest.getAbsoluteTop()+5);
				d.onSubmit(new ClickHandler(){
					@Override
					public void onClick(ClickEvent event) {
						if(d.getAnswer()==null){return;}
						TestBean t = new TestBean();
						EncoderTestBean r = new EncoderTestBean();
						t.setTestid(testid);
						t.setName(d.getAnswer());
						t.setType(SensorType.ENCODER);
						t.setDescription(descriptionTextArea.getText());
						r.setMotorSpeed(speedBox.getValue());
						r.setReadingFrequency(sampleRateBox.getValue());
						r.setDirection(Direction.valueOf(directionComboBox.getValue(directionComboBox.getSelectedIndex())));
						t.setMetadata(r);
						addTest(t, btnCreateTest.getAbsoluteLeft()+5, btnCreateTest.getAbsoluteTop()+5,testid!=-1);
						d.hide();
						Window.Location.assign("viewtests.do");
					}
				});
				d.onCancel(new ClickHandler(){
					@Override
					public void onClick(ClickEvent event) {
						d.hide();				
					}
				});	
			}
		});

		encGrid.setWidget(3, 1, btnCreateTest);

		final Grid rfGrid = new Grid(5, 2);
		rfGrid.setSize("100%", "100%");

		Label lblNumberOfReadings = new Label("Number of Readings:");
		rfGrid.setWidget(0, 0, lblNumberOfReadings);

		final IntegerBox numReadingsBox = new IntegerBox();
		rfGrid.setWidget(0, 1, numReadingsBox);

		Label lblReadingRepetitions = new Label("Reading Repetitions:");
		rfGrid.setWidget(1, 0, lblReadingRepetitions);

		final IntegerBox numRepsBox = new IntegerBox();
		rfGrid.setWidget(1, 1, numRepsBox);

		Label lblStartDistance = new Label("Start Distance:");
		rfGrid.setWidget(2, 0, lblStartDistance);

		final IntegerBox startDistBox = new IntegerBox();
		rfGrid.setWidget(2, 1, startDistBox);

		Label lblEndDistance = new Label("End Distance:");
		rfGrid.setWidget(3, 0, lblEndDistance);

		final IntegerBox endDistBox = new IntegerBox();
		rfGrid.setWidget(3, 1, endDistBox);

		final Button createTestButton = new Button(buttonText);
		createTestButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				final DialogPrompt d = new DialogPrompt(dialogText);
				d.show(createTestButton.getAbsoluteLeft()+5, createTestButton.getAbsoluteTop()+5);
				d.onSubmit(new ClickHandler(){
					@Override
					public void onClick(ClickEvent event) {
						if(d.getAnswer()==null){return;}
						TestBean t = new TestBean();
						RFTestBean r = new RFTestBean();
						t.setTestid(testid);
						t.setName(d.getAnswer());
						t.setType(SensorType.RF);
						t.setDescription(descriptionTextArea.getText());
						r.setNumReadings(numReadingsBox.getValue());
						r.setNumEachReading(numRepsBox.getValue());
						r.setStartDistance(startDistBox.getValue());
						r.setEndDistance(endDistBox.getValue());
						t.setMetadata(r);
						addTest(t, createTestButton.getAbsoluteLeft()+5, createTestButton.getAbsoluteTop()+5,testid!=-1);
						d.hide();
						Window.Location.assign("viewtests.do");
					}

				});
				d.onCancel(new ClickHandler(){
					@Override
					public void onClick(ClickEvent event) {
						d.hide();				
					}
				});		
			}
		});
		rfGrid.setWidget(4, 1, createTestButton);

		comboBox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				if(comboBox.getItemText(comboBox.getSelectedIndex()).equals("Rangefinder")){
					if(decoratedStackPanel.getWidgetCount() > 2){decoratedStackPanel.remove(2);}
					decoratedStackPanel.add(rfGrid, "Test Properties", false);
				}
				else if(comboBox.getItemText(comboBox.getSelectedIndex()).equals("Encoder")){
					if(decoratedStackPanel.getWidgetCount() > 2){decoratedStackPanel.remove(2);}
					decoratedStackPanel.add(encGrid, "Test Properties", false);
				}
			}
		});

		if(testid != -1){
			asyncAccess.lookupTest(testid, new AsyncCallback<TestBean>(){
				@Override
				public void onFailure(Throwable caught) {
					Window.alert(caught.getMessage());
				}
				@Override
				public void onSuccess(final TestBean result) {
					if(result.getType()==SensorType.ENCODER){
						EncoderTestBean r = (EncoderTestBean) result.getMetadata();
						if(!comboBox.getItemText(comboBox.getSelectedIndex()).equals("Encoder")){
							comboBox.setSelectedIndex((comboBox.getSelectedIndex()+1)%2);
							if(decoratedStackPanel.getWidgetCount() > 2){decoratedStackPanel.remove(2);}
							decoratedStackPanel.add(encGrid, "Test Properties", false);
						}
						descriptionTextArea.setText(result.getDescription());
						speedBox.setValue(r.getMotorSpeed());
						sampleRateBox.setValue(r.getReadingFrequency());
						while(!directionComboBox.getValue(directionComboBox.getSelectedIndex()).equals(r.getDirection().toString())){
							directionComboBox.setSelectedIndex((directionComboBox.getSelectedIndex()+1)%directionComboBox.getItemCount());
						}
					}
					else if(result.getType()==SensorType.RF){
						RFTestBean r = (RFTestBean) result.getMetadata();
						if(!comboBox.getItemText(comboBox.getSelectedIndex()).equals("Rangefinder")){
							comboBox.setSelectedIndex((comboBox.getSelectedIndex()+1)%2);
							if(decoratedStackPanel.getWidgetCount() > 2){decoratedStackPanel.remove(2);}
							decoratedStackPanel.add(rfGrid, "Test Properties", false);
						}
						descriptionTextArea.setText(result.getDescription());
						numReadingsBox.setValue(r.getNumReadings());
						numRepsBox.setValue(r.getNumEachReading());
						startDistBox.setValue(r.getStartDistance());
						endDistBox.setValue(r.getEndDistance());
						final Button runTest = new Button ("Run Test");
						runTest.addClickHandler(new ClickHandler(){
							@Override
							public void onClick(ClickEvent event) {
								TestBean t = new TestBean();
								t.setTestid(testid);
								t.setName(result.getName());
								t.setType(SensorType.RF);
								t.setDescription(result.getDescription());
								t.setMetadata(result.getMetadata());
								runTest(t, runTest.getAbsoluteLeft()+5, runTest.getAbsoluteTop()+5);
							}
						});
						rootPanel.add(runTest);
					}
					asyncAccess.testHasNoResults(result.getTestid(),new AsyncCallback<Boolean>(){
						@Override
						public void onFailure(Throwable caught) {
							//ignore
						}
						@Override
						public void onSuccess(Boolean result) {
							createTestButton.setEnabled(result);
							btnCreateTest.setEnabled(result);
						}				
					});
				}
			});
		}
	}


	private void runTest(final TestBean t, final int i, final int j) {
		final DialogBox b = new DialogBox();
		b.setAnimationEnabled(true);
		b.setGlassEnabled(true);
		b.setPopupPosition(i, j);
		FlowPanel f = new FlowPanel();
		final ListBox c = new ListBox();
		final Button submit = new Button("Submit");
		Button cancel = new Button("Cancel");
		f.add(c);
		f.add(submit);
		f.add(cancel);
		b.setWidget(f);
		b.setText("Select a robot to run the test on");
		asyncAccess.retrieveAll(new AsyncCallback<List<RobotBean>>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			@Override
			public void onSuccess(final List<RobotBean> result) {
				for(RobotBean r : result){
					c.addItem(r.getName());
				}
				submit.addClickHandler(new ClickHandler(){
					RobotBean selectedRobot = null;
					List<SensorBean> selectedSensors = new java.util.ArrayList<SensorBean>();
					@Override
					public void onClick(ClickEvent event) {
						if(selectedRobot == null){
							selectedRobot = result.get(c.getSelectedIndex());
							asyncAccess.lookupSensors(selectedRobot.getSensors(), new AsyncCallback<List<SensorBean>>(){
								@Override
								public void onFailure(Throwable caught) {
									Window.alert(caught.getMessage());
								}
								@Override
								public void onSuccess(List<SensorBean> result) {
									c.clear();
									for(SensorBean s:result){
										if(s.getType()==SensorBean.SensorType.RF){
											c.addItem(s.getName());
											selectedSensors.add(s);
										}
									}
								}
							});
							b.setText("Select the robot sensor to use");
						}
						else{
							ResultBean res = new ResultBean();
							res.setRobotid(selectedRobot.getId());
							res.setSensorid(selectedSensors.get(c.getSelectedIndex()).getId());
							res.setTestid(t.getTestid());
							asyncAccess.runTest(res,t, new AsyncCallback<ResultBean>(){
								@Override
								public void onFailure(Throwable caught) {
									Window.alert("Test Run Failed: "+caught.getMessage());
								}
								@Override
								public void onSuccess(ResultBean result) {
									final PopupPanel p = new PopupPanel(true);
									p.addCloseHandler(new CloseHandler<PopupPanel>(){
										@Override
										public void onClose(
												CloseEvent<PopupPanel> event) {
											Window.Location.assign("recenttests.do");
										}
									});
									p.setAnimationEnabled(true);
									p.setGlassEnabled(true);
									p.setPopupPosition(i+5, j+5);
									p.setWidget(new Label("Test run on " + result.getDate().toString()));
									p.show();
								}
							});
							b.hide();
						}
					}
				});
				b.show();
			}
		});

		cancel.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				b.hide();
			}
		});
	}

	protected void addTest(final TestBean t, int i, int j, boolean update) {		
		final PopupPanel p = new PopupPanel(true);
		p.setAnimationEnabled(true);
		p.setGlassEnabled(true);
		p.setPopupPosition(i, j);
		p.addCloseHandler(new CloseHandler<PopupPanel>(){
			@Override
			public void onClose(CloseEvent<PopupPanel> event) {
				Window.Location.assign("viewtests.do");	
			}
		});
		if(update){
			asyncAccess.updateTest(t, new AsyncCallback<TestBean>(){
				@Override
				public void onFailure(Throwable caught) {
					p.setTitle("Error");
					p.setWidget(new Label(caught.toString()));
					p.show();
				}
				@Override
				public void onSuccess(TestBean result) {
					p.setTitle("Success");
					p.setWidget(new Label(result.getName()+" updated with id "+t.getTestid()));
					p.show();
				}
			});
		}
		else{
			asyncAccess.addTest(t, new AsyncCallback<TestBean>(){
				@Override
				public void onFailure(Throwable caught) {
					p.setTitle("Error");
					p.setWidget(new Label(caught.toString()));
					p.show();
				}
				@Override
				public void onSuccess(TestBean result) {
					p.setTitle("Success");
					p.setWidget(new Label(result.getName()+" created with id "+result.getTestid()));
					p.show();
				}
			});
		}
	}

	private void createRobotView() {
		RootPanel rootPanel = RootPanel.get("robot");
		Integer robotId = Integer.parseInt(rootPanel.getTitle());
		rootPanel.setTitle("");

		final VerticalPanel verticalPanel = new VerticalPanel();
		rootPanel.add(verticalPanel);


		//Display Robot Name Header
		final HTML htmltitle = new HTML("<h2>Robot Info Page</h2>", true);
		verticalPanel.add(htmltitle);


		//Display Robot Tests Table
		//CellTable<TestBean> testTable = new CellTable<TestBean>();
		//verticalPanel.add(testTable);

		//Get Robot info
		asyncAccess.lookupRobot(robotId.intValue(), new AsyncCallback<RobotBean>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			@Override
			public void onSuccess(RobotBean result) {
				htmltitle.setHTML("<h2>"+result.getName()+" Info Page</h2>");
				verticalPanel.add(new HTML("<h3>Available Sensors</h3>", true));
				verticalPanel.add(buildSensorTable(result.getSensors()));
				verticalPanel.add(new HTML("<br/><h3>Recent Tests</h3>", true));
				verticalPanel.add(buildResultsTable(result.getId(), 15, null, null, null));

			}
		});
	}

	protected VerticalPanel buildResultsTable(int robotId, int numResults, String robotName, String testName, String sensorName) {
		VerticalPanel vPanel = new VerticalPanel();
		final ProvidesKey<ResultDisplayBean> resultKeyProvider = new ProvidesKey<ResultDisplayBean>(){
			@Override
			public Object getKey(ResultDisplayBean item) {
				return item.getResultid();
			}		
		};

		//Display Robot Available Sensors Table
		final CellTable<ResultDisplayBean> resultTable = new CellTable<ResultDisplayBean>(resultKeyProvider);

		// Add a selection model so we can select cells.
		final SelectionModel<ResultDisplayBean> selectionModel = new MultiSelectionModel<ResultDisplayBean>(resultKeyProvider);
		resultTable.setSelectionModel(selectionModel, DefaultSelectionEventManager.<ResultDisplayBean> createCheckboxManager());

		asyncAccess.lookupRobotResults(robotId, numResults, robotName, testName, sensorName, new AsyncCallback<List<ResultDisplayBean>>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			@Override
			public void onSuccess(List<ResultDisplayBean> result) {
				resultData = new ListDataProvider<ResultDisplayBean>(result,resultKeyProvider);

				//create selection column
				resultTable.addColumn(new Column<ResultDisplayBean, Boolean>(
						new CheckboxCell(true, false)) {
					@Override
					public Boolean getValue(ResultDisplayBean object) {
						// Get the value from the selection model.
						return selectionModel.isSelected(object);
					}
				}, SafeHtmlUtils.fromSafeConstant("<br/>"));

				//create test name column
				resultTable.addColumn(new Column<ResultDisplayBean, String>(
						new TextCell()) {
					@Override
					public String getValue(ResultDisplayBean object) {
						return object.getResultid()+"";
					}
				}, "Result UID");
				
				//create test name column
				resultTable.addColumn(new Column<ResultDisplayBean, String>(
						new TextCell()) {
					@Override
					public String getValue(ResultDisplayBean object) {
						return object.getRobotName();
					}
				}, "Robot Name");
				
				//create test name column
				resultTable.addColumn(new Column<ResultDisplayBean, String>(
						new TextCell()) {
					@Override
					public String getValue(ResultDisplayBean object) {
						return object.getTestName();
					}
				}, "Test Name");

				//create sensor name column
				resultTable.addColumn(new Column<ResultDisplayBean, String>(
						new TextCell()) {
					@Override
					public String getValue(ResultDisplayBean object) {
						return object.getSensorName();
					}
				}, "Sensor Name");

				//create date column
				resultTable.addColumn(new Column<ResultDisplayBean, java.util.Date>(
						new DateCell()) {
					@Override
					public Date getValue(ResultDisplayBean object) {
						return object.getDate();
					}
				}, "Date");

				// View Results
//				Column<ResultDisplayBean, String> viewColumn = new Column<ResultDisplayBean,String>(
//						new ButtonCell()){
//					@Override
//					public String getValue(ResultDisplayBean object) {
//						return "View Results";
//					}
//				};
//				viewColumn.setFieldUpdater(new FieldUpdater<ResultDisplayBean,String>(){
//					@Override
//					public void update(int index, ResultDisplayBean object, String value) {
//						final FormPanel form = new FormPanel(new NamedFrame("_self"));
//						form.setAction("viewresults.do");
//						form.setMethod(FormPanel.METHOD_POST);
//						String resultIDs = "";
//						ResultDisplayBean first = null;
//						for(ResultDisplayBean disp : resultData.getList()){
//							if(resultTable.getSelectionModel().isSelected(disp)){
//								if(resultIDs.length()>0 && !first.getTestName().equals(disp.getTestName())){
//									continue;
//								}
//								else{
//									first=disp;
//								}
//								resultIDs+=disp.getResultid()+";";
//							}
//						}
//						form.setEncoding(FormPanel.ENCODING_URLENCODED);
//						if(resultIDs.length()>0){
//							//remove trailing semicolon
//							resultIDs = resultIDs.substring(0, resultIDs.length()-1);
//							form.setWidget(new Hidden("results",resultIDs));
//							form.submit();
//						}
//					}
//				});
//				resultTable.addColumn(viewColumn);
				
				resultData.addDataDisplay(resultTable);
				//TODO make stuff modifiable
			}
		});

		Button graph = new Button("Graph");
		graph.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				final FormPanel form = new FormPanel(new NamedFrame("_self"));
				form.setAction("viewresults.do");
				form.setMethod(FormPanel.METHOD_POST);
				String resultIDs = "";
				ResultDisplayBean first = null;
				for(ResultDisplayBean disp : resultData.getList()){
					if(resultTable.getSelectionModel().isSelected(disp)){
						if(resultIDs.length()>0 && !first.getTestName().equals(disp.getTestName())){
							continue;
						}
						else{
							first=disp;
						}
						resultIDs+=disp.getResultid()+";";
					}
				}
				form.setEncoding(FormPanel.ENCODING_URLENCODED);
				if(resultIDs.length()>0){
					//remove trailing semicolon
					resultIDs = resultIDs.substring(0, resultIDs.length()-1);
					form.setWidget(new Hidden("results",resultIDs));
					form.submit();
				}
			}
		});
		vPanel.add(resultTable);
		vPanel.add(graph);
		return vPanel;
	}

	protected CellTable<SensorBean> buildSensorTable(int sensors) {
		final ProvidesKey<SensorBean> sensorKeyProvider = new ProvidesKey<SensorBean>(){
			@Override
			public Object getKey(SensorBean item) {
				return item.getId();
			}		
		};

		//Display Robot Available Sensors Table
		final CellTable<SensorBean> sensorTable = new CellTable<SensorBean>(sensorKeyProvider);


		// Add a selection model so we can select cells.
		final SelectionModel<SensorBean> selectionModel = new MultiSelectionModel<SensorBean>(sensorKeyProvider);
		sensorTable.setSelectionModel(selectionModel, DefaultSelectionEventManager.<SensorBean> createCheckboxManager());

		asyncAccess.lookupSensors(sensors, new AsyncCallback<List<SensorBean>>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			@Override
			public void onSuccess(List<SensorBean> result) {
				sensorData = new ListDataProvider<SensorBean>(result,sensorKeyProvider);

				//Attach a column sort handler to the ListDataProvider to sort the list.
				ListHandler<SensorBean> sortHandler = new ListHandler<SensorBean>(result);
				sensorTable.addColumnSortHandler(sortHandler);

				//create selection column
				/*sensorTable.addColumn(new Column<SensorBean, Boolean>(
						new CheckboxCell(true, false)) {
					@Override
					public Boolean getValue(SensorBean object) {
						// Get the value from the selection model.
						return selectionModel.isSelected(object);
					}
				}, SafeHtmlUtils.fromSafeConstant("<br/>"));*/

				//create name column
				sensorTable.addColumn(new Column<SensorBean, String>(
						new TextCell()) {
					@Override
					public String getValue(SensorBean object) {
						return object.getName();
					}
				}, "Name");

				//create sensor type column
				sensorTable.addColumn(new Column<SensorBean, String>(
						new TextCell()) {
					@Override
					public String getValue(SensorBean object) {
						return object.getType().toString();
					}
				}, "Sensor Type");

				sensorData.addDataDisplay(sensorTable);
				//TODO make sensors removable
			}
		});

		return sensorTable;
	}

	private void createRobotTable() {
		RootPanel rootPanel = RootPanel.get("robotTable");
		final ProvidesKey<RobotBean> keyProvider = new ProvidesKey<RobotBean>(){
			@Override
			public Object getKey(RobotBean item) {
				return item.getId();
			}
		};
		final CellTable<RobotBean> cellTable = new CellTable<RobotBean>(keyProvider);

		rootPanel.add(cellTable);

		asyncAccess.retrieveAll(new AsyncCallback<List<RobotBean>>(){

			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}

			@Override
			public void onSuccess(List<RobotBean> result) {
				robotData = new ListDataProvider<RobotBean>(result,keyProvider);

				//Attach a column sort handler to the ListDataProvider to sort the list.
				ListHandler<RobotBean> sortHandler = new ListHandler<RobotBean>(result);
				cellTable.addColumnSortHandler(sortHandler);


				// Add a selection model so we can select cells.
				final SelectionModel<RobotBean> selectionModel = new SingleSelectionModel<RobotBean>(keyProvider);
				cellTable.setSelectionModel(selectionModel, DefaultSelectionEventManager.<RobotBean> createCheckboxManager());

				initRobotTableColumns(cellTable,sortHandler,selectionModel);

				robotData.addDataDisplay(cellTable);
			}

		});
	}

	private void createMenu(){
		MenuBar menuBar = new MenuBar(false);
		MenuBar menuBar_1 = new MenuBar(true);

		RootPanel.get("menu").add(menuBar);

		MenuItem webcam = new MenuItem("Webcam",false, new Command(){
			@Override
			public void execute() {
				Window.Location.assign("webcam.do");	
			}
		});
		
		MenuItem mntmRobots = new MenuItem("Robots", false, menuBar_1);

		MenuItem mntmView = new MenuItem("View", false, (Command) null);
		mntmView.setCommand(new Command(){
			@Override
			public void execute() {
				Window.Location.assign("viewrobots.do");
			}
		});
		menuBar_1.addItem(mntmView);

		MenuItemSeparator separator = new MenuItemSeparator();
		menuBar_1.addSeparator(separator);

		final MenuItem mntmCreate = new MenuItem("Create", false, (Command) null);
		menuBar_1.addItem(mntmCreate);

		menuBar.addItem(mntmRobots);
		MenuBar menuBar_2 = new MenuBar(true);

		MenuItem mntmTests = new MenuItem("Tests", false, menuBar_2);

		MenuItem mntmEdit = new MenuItem("View/Edit", false, (Command) null);
		mntmEdit.setCommand(new Command(){
			@Override
			public void execute() {
				Window.Location.assign("viewtests.do");
			}
		});
		menuBar_2.addItem(mntmEdit);

		MenuItem mntmCreate_1 = new MenuItem("Create", false, (Command) null);
		mntmCreate_1.setCommand(new Command(){
			@Override
			public void execute() {
				Window.Location.assign("testcreate.do");
			}
		});
		menuBar_2.addItem(mntmCreate_1);

		menuBar.addItem(mntmTests);
		MenuBar menuBar_3 = new MenuBar(true);

		MenuItem mntmResults = new MenuItem("Results", false, menuBar_3);

		MenuItem mntmRecent = new MenuItem("Recent", false, (Command) null);
		mntmRecent.setCommand(new Command(){
			@Override
			public void execute() {
				Window.Location.assign("recenttests.do");	
			}
		});
		menuBar_3.addItem(mntmRecent);

		MenuItem mntmSearch = new MenuItem("Search", false, new Command(){
			@Override
			public void execute() {
				Window.Location.assign("search.do");
			}
		});
		menuBar_3.addItem(mntmSearch);
		menuBar.addItem(mntmResults);

		menuBar.addItem(webcam);
		
		// Create the popup dialog box
		final DialogBox dialogBox = new DialogBox();
		dialogBox.setText("Please Enter A Name For The New Robot");
		dialogBox.setAnimationEnabled(true);
		dialogBox.setGlassEnabled(true);
		final Button enterButton = new Button("Submit");
		final Button closeButton = new Button("Close");
		final TextBox nameBox = new TextBox();
		// We can set the id of a widget by accessing its Element
		enterButton.getElement().setId("enterButton");
		closeButton.getElement().setId("closeButton");
		FlowPanel dialogFPanel = new FlowPanel();
		dialogFPanel.add(nameBox);
		dialogFPanel.add(enterButton);
		dialogFPanel.add(closeButton);
		dialogBox.setWidget(dialogFPanel);

		mntmCreate.setCommand(new Command(){
			@Override
			public void execute() {
				//				String name = Window.prompt("Enter the new robot name:", "");
				final DialogPrompt d = new DialogPrompt("Enter the new robot name:");
				d.show(mntmCreate.getAbsoluteLeft()+5, mntmCreate.getAbsoluteTop()+5);
				d.onSubmit(new ClickHandler(){
					@Override
					public void onClick(ClickEvent event) {
						addRobot(d.getAnswer(), mntmCreate.getAbsoluteLeft()+5, mntmCreate.getAbsoluteTop()+5);
						d.hide();
					}
				});
				d.onCancel(new ClickHandler(){
					@Override
					public void onClick(ClickEvent event) {
						d.hide();				
					}
				});
			}	
		});

		// Add a handler to close the DialogBox
		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});

		//Add a handler to create a new robot entry
		enterButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				RobotBean r = new RobotBean();
				r.setName(nameBox.getText());
				final PopupPanel p = new PopupPanel(true);
				asyncAccess.addRobot(r, new AsyncCallback<RobotBean>(){

					@Override
					public void onFailure(Throwable caught) {
						p.setTitle("Error");
						p.setWidget(new Label(caught.toString()));
						p.center();
						p.show();
					}

					@Override
					public void onSuccess(RobotBean result) {
						p.setTitle("Success");
						p.setWidget(new Label(result.getName()+" created with id "+result.getId()));
						p.center();
						p.show();
					}
				});
				dialogBox.hide();
			}
		});
	}

	private void addRobot(String name,int left, int top){
		if(name!=null){
			RobotBean r = new RobotBean();
			r.setName(name);
			final PopupPanel p = new PopupPanel(true);
			p.setAnimationEnabled(true);
			p.setGlassEnabled(true);
			p.setPopupPosition(left, top);
			p.addCloseHandler(new CloseHandler<PopupPanel>(){
				@Override
				public void onClose(CloseEvent<PopupPanel> event) {
					Window.Location.assign("viewrobots.do");	
				}
			});
			asyncAccess.addRobot(r, new AsyncCallback<RobotBean>(){
				@Override
				public void onFailure(Throwable caught) {
					p.setTitle("Error");
					p.setWidget(new Label(caught.toString()));
					p.show();
				}
				@Override
				public void onSuccess(RobotBean result) {
					p.setTitle("Success");
					p.setWidget(new Label(result.getName()+" created with id "+result.getId()));
					p.show();
				}
			});
		}
	}

	private void initRobotTableColumns(CellTable<RobotBean> cellTable, ListHandler<RobotBean> sortHandler,
			final SelectionModel<RobotBean> selectionModel) {
		/*Column<RobotBean, Boolean> checkColumn = new Column<RobotBean, Boolean>(
				new CheckboxCell(true, false)) {
			@Override
			public Boolean getValue(RobotBean object) {
				// Get the value from the selection model.
				return selectionModel.isSelected(object);
			}
		};
		cellTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));*/
		//cellTable.setColumnWidth(checkColumn, 40, Unit.PX);

		// Name
		Column<RobotBean, String> nameColumn = new Column<RobotBean, String>(
				new TextCell()) {
			@Override
			public String getValue(RobotBean object) {
				return object.getName();
			}
		};
		//nameColumn.setSortable(true);
		sortHandler.setComparator(nameColumn, new Comparator<RobotBean>() {
			public int compare(RobotBean o1, RobotBean o2) {
				return o1.getName().compareToIgnoreCase(o2.getName());
			}
		});
		cellTable.addColumn(nameColumn, "Name");
		cellTable.getColumnSortList().push(nameColumn);
		cellTable.addColumnSortHandler(sortHandler);
		//cellTable.setColumnWidth(firstNameColumn, 20, Unit.PCT);

		// Sensor
		Column<RobotBean, String> sensorColumn = new Column<RobotBean,String>(
				new TextCell()){
			@Override
			public String getValue(RobotBean object) {
				return Integer.toBinaryString(object.getSensors());
			}
		};
		cellTable.addColumn(sensorColumn, "Sensor Status Code");

		// View Robot
		Column<RobotBean, String> viewColumn = new Column<RobotBean,String>(
				new ButtonCell()){
			@Override
			public String getValue(RobotBean object) {
				return object.getName() + " info page";
			}
		};
		viewColumn.setFieldUpdater(new FieldUpdater<RobotBean,String>(){
			@Override
			public void update(int index, RobotBean object, String value) {
				final FormPanel form = new FormPanel(new NamedFrame("_self"));
				form.setAction("viewrobot.do");
				form.setMethod(FormPanel.METHOD_POST);
				form.setWidget(new Hidden("id",object.getId()+""));
				form.setEncoding(FormPanel.ENCODING_URLENCODED);
				form.submit();
			}
		});
		cellTable.addColumn(viewColumn);
	}
}
